#include <poll.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/fcntl.h>

#define MSG(args...) printf(args)

static int gpio_export(int pin)  
{  
    char buffer[64] = {0};  
    int len = -1;  
    int fd = -1;  

    fd = open("/sys/class/gpio/export", O_WRONLY);  
    if (fd < 0) 
	{ 
        MSG("Failed to open export for writing!\n");  
		close(fd);
        return(-1);  
    }  
	
    len = snprintf(buffer, sizeof(buffer), "%d", pin);  
    if (write(fd, buffer, len) < 0)
	{  
        MSG("Failed to export gpio!");  
		close(fd);
        return -1;  
    } 
	
    close(fd);  
    return 0; 
}  

static int gpio_unexport(int pin)  
{  
    char buffer[64] = {0};  
    int len = -1;  
    int fd = -1;   

    fd = open("/sys/class/gpio/unexport", O_WRONLY);  
    if (fd < 0) 
	{  
        MSG("Failed to open unexport for writing!\n");  
		close(fd);
        return -1;  
    }  

    len = snprintf(buffer, sizeof(buffer), "%d", pin);  
    if (write(fd, buffer, len) < 0) 
	{  
        MSG("Failed to unexport gpio!");  
		close(fd);
        return -1;  
    }  

    close(fd);  
    return 0;  
} 

//dir: 0-->IN, 1-->OUT
static int gpio_direction(int pin, int dir)  
{
    static const char dir_str[] = "in\0out";  
    char path[64] = {0};  
    int fd = -1;  
  
    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);  
    fd = open(path, O_WRONLY);  
    if (fd < 0)
	{  
        MSG("Failed to open gpio direction for writing!\n");  
		close(fd);
        return -1;  
    }  

    if (write(fd, &dir_str[dir == 0 ? 0 : 3], dir == 0 ? 2 : 3) < 0)
	{  
        MSG("Failed to set direction!\n");  
		close(fd);
        return -1;  
    }  
	
    close(fd);  
    return 0;  
}

// none表示引脚为输入，不是中断引脚
// rising表示引脚为中断输入，上升沿触发
// falling表示引脚为中断输入，下降沿触发
// both表示引脚为中断输入，边沿触发
// 0-->none, 1-->rising, 2-->falling, 3-->both
static int gpio_edge(int pin, int edge)
{
	const char dir_str[] = "none\0rising\0falling\0both"; 
	int ptr;
	char path[64] = {0};  
	int fd = -1; 

	switch(edge)
	{
		case 0:
			ptr = 0;
			break;
		case 1:
			ptr = 5;
			break;
		case 2:
			ptr = 12;
			break;
		case 3:
			ptr = 20;
			break;
		default:
			ptr = 0;
	} 
	snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", pin);  
	
	fd = open(path, O_WRONLY);  
	if (fd < 0) 
	{  
		MSG("Failed to open gpio edge for writing!\n");  
		close(fd); 
		return -1;  
	}  

	if (write(fd, &dir_str[ptr], strlen(&dir_str[ptr])) < 0) 
	{  
		MSG("Failed to set edge!\n");  
		close(fd); 
		return -1;  
	}  

	close(fd);  
	return 0;  
}

//初始化按键1
void init_gpio1(void)
{
	gpio_unexport(1);
	gpio_export(1);
	gpio_direction(1, 0);
	gpio_edge(1, 2);
}

//初始化按键2
void init_gpio2(void)
{
	gpio_unexport(2);
	gpio_export(2);
	gpio_direction(2, 0);
	gpio_edge(2, 2);
}

void gpio_btns_init(void)
{
	init_gpio1();
	init_gpio2();
}

